package com.authine.cloudpivot.ext.controller.person;

import cn.hutool.core.lang.Assert;
import com.authine.cloudpivot.engine.api.model.organization.UserModel;
import com.authine.cloudpivot.engine.api.model.runtime.BizObjectCreatedModel;
import com.authine.cloudpivot.engine.api.model.runtime.WorkItemModel;
import com.authine.cloudpivot.engine.api.model.runtime.WorkflowInstanceModel;
import com.authine.cloudpivot.engine.enums.status.SequenceStatus;
import com.authine.cloudpivot.ext.Utils.CustomSchemaCode;
import com.authine.cloudpivot.ext.service.CloudSqlService;
import com.authine.cloudpivot.web.api.config.EducationEnum;
import com.authine.cloudpivot.web.api.config.FirstEducationEnum;
import com.authine.cloudpivot.web.api.controller.base.BaseController;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 人员信息记录 人事信息
 **/
@RestController
@RequestMapping("/public/personnelInfo")
@Slf4j
public class PersonnelInfoController extends BaseController {

    @Autowired
    CloudSqlService sqlService;

    /**
     * 人员信息记录 人事信息  审批流完成后 数据写到-人员信息记录 基础表 基础，补全基础表的数据
     */
    @RequestMapping("finish")
    public void finish(String bizId) {
        BizObjectCreatedModel bizObject = getBizObjectFacade().getBizObject(CustomSchemaCode.personnelInfo, bizId);

        //personnelInfoDetail  人员信息记录 人事信息子表
        List<Map<String, Object>> list = (List<Map<String, Object>>) bizObject.get("personnelInfoDetail");

        String now = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        String approval = "";

        for (Map<String, Object> map : list) {


            try {
                //将子表中数据处理，随后更新至【人员信息记录 基础表】
                Map<String, Object> data = fileInfoBaseMap(map, now, approval);
                String id = existsBizObject(map);
                if (StringUtils.isEmpty(id)) {
                    //判断是否已存在，如果不存在，放弃这条数据，直接跳过此次循环
                    log.info("人员信息记录 人事信息审批完成后，子表中的人员代码：{}，在基础数据表无数据，跳过更新", map.get("personNumber"));
                    continue;
                } else if (StringUtils.isNotEmpty(id)) {
                    data.put("id", id);
                }

                BizObjectCreatedModel model = new BizObjectCreatedModel(CustomSchemaCode.personInfoBase, data, false);
                model.setSequenceStatus(SequenceStatus.COMPLETED.name());
                id = getBizObjectFacade().saveBizObject(CustomSchemaCode.adminUserId, model, false);
                log.info("基础表-人员信息基础更新成功 ");
                //调用存储过程
                callProcess(id);

            } catch (Exception e) {
                String companyNumber = (String) map.get("companyNumber");
                String personNumber = (String) map.get("personNumber");

                log.info("基础表-人员信息基础操作失败 companyNumber={},personNumber={}", companyNumber, personNumber);
                log.info(e.getMessage(), e);
            }

        }
    }

    @RequestMapping("toVoid")
    public void toVoid(String bizId) {
        BizObjectCreatedModel bizObject = getBizObjectFacade().getBizObject(CustomSchemaCode.toVoidPersonnelInfo, bizId);
        List<Map<String, Object>> list = (List<Map<String, Object>>) bizObject.get("voidPersonnelInfoDetail");

        String now = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        //获取审批人

        String approval = getFileBaseInfoWorkFlowApproval(bizObject);

        for (Map<String, Object> map : list) {


            try {
                //获取数据
                Map<String, Object> data = fileInfoBaseMap(map, now, approval);
                //判断是否已存在
                String id = existsBizObject(data);
                if (StringUtils.isEmpty(id)) {
                    //判断是否已存在，如果不存在，放弃这条数据，直接跳过此次循环
                    log.info("人员信息记录 人事信息审批完成后，子表中的人员代码：{}，在基础数据表无数据，跳过更新", map.get("personNumber"));
                    continue;
                } else if (StringUtils.isNotEmpty(id)) {
                    data.put("id", id);
                }

                BizObjectCreatedModel model = new BizObjectCreatedModel(CustomSchemaCode.personInfoBase, data, false);
                model.setSequenceStatus(SequenceStatus.CANCELED.name());
                id = getBizObjectFacade().saveBizObject(CustomSchemaCode.adminUserId, model, false);
                log.info("基础表-人员信息基础作废操作成功 ");
                //调用存储过程
                callProcessToVoid(id);

            } catch (Exception e) {
                String companyNumber = (String) map.get("companyNumber");
                String personNumber = (String) map.get("personNumber");
                log.info("基础表-人员信息基础作废操作失败 personNumber={},companyNumber={}", personNumber, companyNumber);
                log.info(e.getMessage(), e);
            }

        }
    }


    /**
     * 调用存储过程
     * ------人员信息  人事信息
     * exec   SyncEmpPersonalInfo
     *
     * @param bizId
     * @orgid nvarchar(100),                ----公司FID
     * @EmpCode nvarchar(50),            ----人员代码
     * @ForeignName nvarchar(100),        ----译名
     * @EmpStatus nvarchar(100),        ----状态   0  √    1  x
     * @StatusDesc nvarchar(255),        ----状态说明
     * @BeginDate nvarchar(50),        ----入职日期  YYYY-MM-DD
     * @Departure int,                    ----间断月数
     * @EndDate nvarchar(50),        ----去职日期  YYYY-MM-DD
     * @HR nvarchar(10),        ----人事档案   三种情况：√ 转换为0；x 转换为1；待定 转换为2
     * @ManageDeptFID nvarchar(100),        ----第一岗部门FID
     * @EmpID nvarchar(50),        ----工号
     * @InName nvarchar(50),        ----内部称谓
     * @OutName nvarchar(50),        ----外部称谓
     * @chest	nvarchar(200),		----胸牌
     * @card	nvarchar(200),		----名片
     * @WorkDesc nvarchar(500),        ----工作说明
     * @Auditor nvarchar(50)            ----审批人
     * @FirstPosCode	nvarchar(50)		----第一岗代码
     */
    private void callProcess(String bizId) {

        if (StringUtils.isEmpty(bizId)) {
            return;
        }
        //编写sql
        String tableName = getBizObjectFacade().getTableName(CustomSchemaCode.personInfoBase);
        StringBuilder sql = new StringBuilder("SELECT * from ")
                .append(tableName).append(" where id ='")
                .append(bizId).append("';");
        //查询到入参
        Map<String, Object> map = sqlService.getMap(sql.toString());

        log.info("入参map={}", map);

        //调用存储过程
        String company = MapUtils.getString(map, "company", "");//公司FID
        String personNumber = MapUtils.getString(map, "personNumber", "");//人员代码
        String foreignName = MapUtils.getString(map, "foreignName", "");//译名

        String status = MapUtils.getString(map, "status", "");//状态
        status = "√".equals(status) ? "0" : "1";

        String statusReson = MapUtils.getString(map, "statusReson", "");//状态说明

//        Date beginDateTemp = (Date) map.get("beginDate");//入职日期
//        String beginDate = beginDateTemp == null ? "" : DateFormatUtils.format(beginDateTemp, "yyyy-MM-dd");
        LocalDateTime beginDateTemp = (LocalDateTime) map.get("beginDate");
        String beginDate =  ObjectUtils.isEmpty(beginDateTemp) ? "" : beginDateTemp.toLocalDate().toString();

        Integer departure = MapUtils.getInteger(map, "departure", 0);//间断月数

//        Date endDateTemp = (Date) map.get("endDate");//去职日期
//        String endDate = endDateTemp == null ? "" : DateFormatUtils.format(endDateTemp, "yyyy-MM-dd");
        LocalDateTime endDateTemp = (LocalDateTime) map.get("endDate");
        String endDate =  ObjectUtils.isEmpty(endDateTemp) ? "" : endDateTemp.toLocalDate().toString();

        //check  √   cross  x   blank  待定
        String hr = MapUtils.getString(map, "HR", "");//人事档案
        String firstPosCode = MapUtils.getString(map, "pos1FNumber", "");//第一岗代码

        String hrValue = null;
        switch (hr) {
            case "√":
//                hrValue = "0";
                hrValue = "check";
                break;
            case "×":
//                hrValue = "1";
                hrValue = "cross";
                break;
            case "待定":
//                hrValue = "2";
                hrValue = "blank";
                break;
        }

        String pos1DeptFId = MapUtils.getString(map, "pos1DeptFId", "");//第一岗部门FID
        String empNo = MapUtils.getString(map, "empNo", "");//工号
        String inName = MapUtils.getString(map, "inName", "");//内部称谓
        String outName = MapUtils.getString(map, "outName", "");//外部称谓
        String chestCard = MapUtils.getString(map, "chestCard", "");//胸卡
        String businessCard = MapUtils.getString(map, "businessCard", "");//名片
        String workDesc = MapUtils.getString(map, "workDesc", "");//工作说明
        String auditer = MapUtils.getString(map, "auditer", "");//审批人


//        Assert.isFalse(StringUtils.isEmpty(company), "{}不能为空", "company");
//        Assert.isFalse(StringUtils.isEmpty(personNumber), "{}不能为空", "personNumber");
//        Assert.isFalse(StringUtils.isEmpty(status), "{}不能为空", "status");
//        Assert.isFalse(StringUtils.isEmpty(beginDate), "{}不能为空", "beginDate");
//        Assert.isFalse(StringUtils.isEmpty(hr), "{}不能为空", "hr");
//        Assert.isFalse(StringUtils.isEmpty(pos1DeptFId), "{}不能为空", "pos1DeptFId");
//        Assert.isFalse(StringUtils.isEmpty(empNo), "{}不能为空", "empNo");
//        Assert.isFalse(StringUtils.isEmpty(inName), "{}不能为空", "inName");
//        Assert.isFalse(StringUtils.isEmpty(outName), "{}不能为空", "outName");


        String execSql = String.format("exec [HG_LINK].[hg].[dbo].SyncEmpPersonalInfo '%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s'",
                company, personNumber, foreignName, status, statusReson, beginDate, departure, endDate, hrValue, pos1DeptFId, empNo, inName, outName, chestCard, businessCard, workDesc, auditer,firstPosCode);

        log.info("\n==========准备调用存储过程:{}", execSql);

        sqlService.execute(CloudSqlService.htEas, execSql);

        log.info("\n=============存储过程执行完成");

    }

    /**
     * 调用作废存储过程
     * --------人员信息记录   人事信息 作废
     * exec    EmpPersonalVoid
     *
     * @param bizId
     * @CompanyFID nvarchar(100),            ----公司FID
     * @EmpCode nvarchar(100)            ----人员代码
     */
    private void callProcessToVoid(String bizId) {

        if (StringUtils.isEmpty(bizId)) {
            return;
        }
        //编写sql
        String tableName = getBizObjectFacade().getTableName(CustomSchemaCode.personInfoBase);
        StringBuilder sql = new StringBuilder("SELECT company,personNumber from ")
                .append(tableName).append(" where id ='")
                .append(bizId).append("';");
        //查询到入参
        Map<String, Object> map = sqlService.getMap(sql.toString());

        log.info("入参map={}", map);

        //调用存储过程

        String company = MapUtils.getString(map, "company", "");
        String personNumber = MapUtils.getString(map, "personNumber", "");

        Assert.isFalse(StringUtils.isEmpty(company), "{}不能为空", "company");
        Assert.isFalse(StringUtils.isEmpty(personNumber), "{}不能为空", "personNumber");


        String execSql = String.format("exec [HG_LINK].[hg].[dbo].EmpPersonalVoid '%s','%s'",
                company, personNumber);

        log.info("\n==========准备调用作废存储过程:{}", execSql);

        sqlService.execute(CloudSqlService.htEas, execSql);

        log.info("\n=============作废存储过程执行完成");

    }

    /**
     * 查询审批人,返回  员工号+姓名
     *
     * @param bizObject
     * @return
     */
    private String getFileBaseInfoWorkFlowApproval(BizObjectCreatedModel bizObject) {
        WorkflowInstanceModel instanceModel = getWorkflowInstanceFacade().getByObjectId(bizObject.getId());
        List<WorkItemModel> workItems = getWorkflowInstanceFacade().getWorkItems(instanceModel.getId(), true);
        final String finalActivityCode = "Activity15";
        Optional<WorkItemModel> first = workItems.stream().filter(a -> a.getActivityCode().equals(finalActivityCode)).findFirst();
        String participant = null;
        if (first.isPresent()) {
            WorkItemModel workItemModel = first.get();
            participant = workItemModel.getParticipant();
        }

        if (participant == null) {
            final String finalActivityCode2 = "Activity3";
            Optional<WorkItemModel> second = workItems.stream().filter(a -> a.getActivityCode().equals(finalActivityCode2)).findFirst();
            if (second.isPresent()) {
                WorkItemModel workItemModel = second.get();
                participant = workItemModel.getParticipant();
            }
        }


        if (participant == null) {
            participant = bizObject.getCreater().getId();
        }

        UserModel user = getOrganizationFacade().getUser(participant);


        return new StringBuilder(user.getEmployeeNo()).append("　").append(user.getName()).toString();
    }


    /**
     * 判断是否已存在
     *
     * @return
     */
    private String existsBizObject(Map data) {

        String tableName = getBizObjectFacade().getTableName(CustomSchemaCode.personInfoBase);
        String companyNumber = (String) data.get("companyNumber");
        String personNumber = (String) data.get("personNumber");

        StringBuilder sql = new StringBuilder("select id  from ").append(tableName)
                .append(" where companyNumber='").append(companyNumber).append("' and personNumber='")
                .append(personNumber).append("';");

        Map<String, Object> map = sqlService.getMap(sql.toString());

        return (String) map.get("id");
    }

    /**
     * 转换成  基础表-总公司档案 的数据
     *
     * @param map
     * @param auditDate
     * @return
     */
    private Map<String, Object> fileInfoBaseMap(Map<String, Object> map, String auditDate, String auditer) {
        Map<String, Object> data = new HashMap<>();
        //公司代码和人员代码 作为查询条件
        //公司代码
        data.put("companyNumber", map.get("companyNumber"));
        //人员代码
        data.put("personNumber", map.get("personNumber"));


        //译名
        data.put("foreignName", map.get("foreignName"));
        //状态说明
        data.put("statusReson", map.get("statusReson"));
        //入职日期
        data.put("beginDate", map.get("beginDate"));
        //间断月数
        data.put("departure", map.get("departure"));
        //去职日期
        data.put("endDate", map.get("endDate"));
        //人事档案
        data.put("HR", map.get("HR"));
        //第一岗部门代码
        data.put("pos1DeptFId", map.get("pos1DeptFId"));
        //第一岗部门代码隐藏
        data.put("pos1DetpFNumber", map.get("pos1DetpFNumber"));
        //第一岗部门
        data.put("pos1DeptName", map.get("pos1DeptName"));

        //第一岗代码
        data.put("pos1FId", map.get("pos1FId"));
        //第一岗代码
        data.put("pos1FNumber", map.get("pos1FNumber"));
        //第一岗
        data.put("pos1FName", map.get("pos1FName"));
        //工号
        data.put("empNo", map.get("empNo"));
        //内部称谓
        data.put("inName", map.get("inName"));
        //外部称谓
        data.put("outName", map.get("outName"));
        //胸卡
        data.put("chestCard", map.get("chestCard"));
        //名片
        data.put("businessCard", map.get("businessCard"));
        //工作说明
        data.put("workDesc", map.get("workDesc"));

        //审批时间
        data.put("auditDate", auditDate);
        //审批人
        data.put("auditer", auditer);

        return data;
    }
}
